package vcsn.entities;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import vcsn.Config;
import vcsn.utils.StringKeyValuePair;

public class CommitPatch {
	private String author;
	private String patchHash;
	private String patchPath;
	private String relationDiffPath;
	private String senderAddr;
	private String buildDate;
	private int estimatedConflict;
	private int estimatedRefacor;
	private List<ConflictOperation> conflictList;
	
	public String getAuthor()			{ return this.author; }
	public String getPatchHash()		{ return this.patchHash; }
	public String getPatchPath()		{ return this.patchPath; }
	public String getRelationDiffPath()	{ return this.relationDiffPath; }
	public String getSenderAddr()		{ return this.senderAddr; }
	public String getBuildDate()		{ return this.buildDate; }
	public int getEstimatedConflict()	{ return this.estimatedConflict; }
	public int getEstimatedRefactor()	{ return this.estimatedRefacor; }
	public List<ConflictOperation> getConflictList() { return this.conflictList; }
	
	public void setAuthor(String value)				{ this.author = value; }
	public void setPatchHash(String value)			{ this.patchHash = value; }
	public void setPatchPath(String value)			{ this.patchPath = value; }
	public void setRelationDiffPath(String value)	{ this.relationDiffPath = value; }
	public void setSenderAddr(String value)			{ this.senderAddr = value; }
	public void setBuildDate(String value)			{ this.buildDate = value; }
	public void setEstimatedConflict(int value)		{ this.estimatedConflict = value; }
	public void setEstimatedRefactor(int value)		{ this.estimatedRefacor = value; }
	public void addRangedElementsIntoConflictList(List<ConflictOperation> conflictList){
		for(int i = 0;i < conflictList.size();i++){
			this.conflictList.add(conflictList.get(i));
		}
//		for(ConflictOperation c : conflictList){
//			this.conflictList.add(c);
//		}
	}
	public void addElementIntoConflictList(ConflictOperation c){
		conflictList.add(c);
	}
	
	public CommitPatch(){
		setBuildDate(new SimpleDateFormat(Config.FormattedDateTimeString).format(new Date()));
		conflictList = new ArrayList<ConflictOperation>();
	}
	
	@Override
	public String toString(){
		String result = "";
		result += Config.propertyCommitPrefix + Config.setOpen;
		result += Config.propertyIDAuthor 					+ Config.equal + this.getAuthor() 								+ Config.separator;
		result += Config.propertyIDPatchHash 				+ Config.equal + this.getPatchHash() 							+ Config.separator;
		result += Config.propertyIDPatchPath 				+ Config.equal + this.getPatchPath() 							+ Config.separator;
		result += Config.propertyIDRelationDiffPath 		+ Config.equal + this.getRelationDiffPath() 					+ Config.separator;
		result += Config.propertyIDSenderAddr 				+ Config.equal + this.getSenderAddr() 							+ Config.separator;
		result += Config.propertyIDBuildDate 				+ Config.equal + this.getBuildDate() 							+ Config.separator;
		result += Config.propertyIDEstimatedConflictCount 	+ Config.equal + Integer.toString(this.getEstimatedConflict()) 	+ Config.separator;
		result += Config.propertyIDEstimatedRefactorCount 	+ Config.equal + Integer.toString(this.getEstimatedRefactor()) 	+ Config.separator;
		for(ConflictOperation c : conflictList){
			if(c instanceof RenameOperation){
				result += Config.propertyConflictPrefix		+ Config.setOpen;
				result += Config.propertyConflictType 		+ Config.equal + Config.propertyConflictTypeRename 				+ Config.separator;
				result += Config.propertyLocatedFile 		+ Config.equal + c.getConflictLocatedFileName() 				+ Config.separator;
				result += Config.propertyLocatedPosition 	+ Config.equal + c.getConflictLocatedPosition() 				+ Config.separator;
				result += Config.propertyOriginIdentifier 	+ Config.equal + ((RenameOperation)c).getOriginIdentifier() 	+ Config.separator;
				result += Config.propertyModifiedIdentifier + Config.equal + ((RenameOperation)c).getModifiedIdentifier() 	+ Config.separator;
				result += Config.setClose + Config.separator;
			}else if(c instanceof AddCommentOperation){
				result += Config.propertyConflictPrefix		+ Config.setOpen;
				result += Config.propertyConflictType 		+ Config.equal + Config.propertyConflictTypeAddComment 			+ Config.separator;
				result += Config.propertyLocatedFile 		+ Config.equal + c.getConflictLocatedFileName() 				+ Config.separator;
				result += Config.propertyLocatedPosition 	+ Config.equal + c.getConflictLocatedPosition() 				+ Config.separator;
				result += Config.propertyCommentString	 	+ Config.equal + ((AddCommentOperation)c).getCommentString() 	+ Config.separator;
				result += Config.setClose + Config.separator;
			}else if(c instanceof AddCastingOperation){
				result += Config.propertyConflictPrefix		+ Config.setOpen;
				result += Config.propertyConflictType 		+ Config.equal + Config.propertyConflictTypeAddCast 				+ Config.separator;
				result += Config.propertyLocatedFile 		+ Config.equal + c.getConflictLocatedFileName() 					+ Config.separator;
				result += Config.propertyLocatedPosition 	+ Config.equal + c.getConflictLocatedPosition() 					+ Config.separator;
				result += Config.propertyOriginIdentifier 	+ Config.equal + ((AddCastingOperation)c).getOriginIdentifier() 	+ Config.separator;
				result += Config.propertyModifiedIdentifier + Config.equal + ((AddCastingOperation)c).getRefinedIdentifier() 	+ Config.separator;
				result += Config.propertyCastTotype			+ Config.equal + ((AddCastingOperation)c).getCastToType() 			+ Config.separator;
				result += Config.setClose + Config.separator;
			}else if(c instanceof RemoveKeyWordOperation){
				result += Config.propertyConflictPrefix						+ Config.setOpen;
				result += Config.propertyConflictType 						+ Config.equal + Config.propertyConflictTypeRemoveKeyword 							+ Config.separator;
				result += Config.propertyLocatedFile 						+ Config.equal + c.getConflictLocatedFileName() 									+ Config.separator;
				result += Config.propertyLocatedPosition 					+ Config.equal + c.getConflictLocatedPosition() 									+ Config.separator;
				result += Config.propertyKeyword		 					+ Config.equal + ((RemoveKeyWordOperation)c).getKeyword() 							+ Config.separator;
				result += Config.propertyFirstParameterStartingPosition 	+ Config.equal + ((RemoveKeyWordOperation)c).getFirstParameterStartingPosition() 	+ Config.separator;
				result += Config.propertyLastParameterEndingPosition 		+ Config.equal + ((RemoveKeyWordOperation)c).getLastParameterEndingPosition() 		+ Config.separator;
				result += Config.setClose + Config.separator;
			}
			
		}
		result += Config.setClose + Config.separator;
		return result;
	}
	
	public CommitPatch toCommitPatch(String patchString){
		CommitPatch patch = new CommitPatch();
		String[] splitedPatchStringList = patchString.split(Config.propertyConflictPrefix);
			String[] propertyList = splitedPatchStringList[0].replace(Config.setOpen + " ", "").replace(Config.setClose, "").split(Config.separator);
			for(String property : propertyList){
				if(property.isEmpty()){
					continue;
				}
				StringKeyValuePair pair;
				if(property.split(Config.equal).length == 1){
					pair = new StringKeyValuePair(property.split(Config.equal)[0], null);
				}else{
					pair = new StringKeyValuePair(property.split(Config.equal)[0], property.split(Config.equal)[1]);
				}
				if(pair.key.equals(Config.propertyIDAuthor)){
					patch.setAuthor(pair.value);
				}else if(pair.key.equals(Config.propertyIDPatchHash)){
					patch.setPatchHash(pair.value);
				}else if(pair.key.equals(Config.propertyIDPatchPath)){
					patch.setPatchPath(pair.value);
				}else if(pair.key.equals(Config.propertyIDRelationDiffPath)){
					patch.setRelationDiffPath(pair.value);
				}else if(pair.key.equals(Config.propertyIDSenderAddr)){
					patch.setSenderAddr(pair.value);
				}else if(pair.key.equals(Config.propertyIDBuildDate)){
					patch.setBuildDate(pair.value);
				}else if(pair.key.equals(Config.propertyIDEstimatedConflictCount)){
					patch.setEstimatedConflict(Integer.parseInt(pair.value));
				}else if(pair.key.equals(Config.propertyIDEstimatedRefactorCount)){
					patch.setEstimatedRefactor(Integer.parseInt(pair.value));
				}
			}
			for(int i = 1; i < splitedPatchStringList.length;i++){
				String[] conflictPropertyList = splitedPatchStringList[i].replace(Config.setOpen + " ", "").replace(Config.setClose, "").split(Config.separator);
				if(conflictPropertyList[0].split(Config.equal)[1].equals(Config.propertyConflictTypeAddComment)){
					AddCommentOperation opt = new AddCommentOperation();
					for(int j = 1; i < conflictPropertyList.length;i++){
						StringKeyValuePair cPair;
						if(conflictPropertyList[i].split(Config.equal).length == 1){
							cPair = new StringKeyValuePair(conflictPropertyList[j].split(Config.equal)[0], null);
						}else{
							cPair = new StringKeyValuePair(conflictPropertyList[j].split(Config.equal)[0], conflictPropertyList[j].split(Config.equal)[1]);
						}
						if(cPair.key.equals(Config.propertyLocatedFile)){
							opt.setConflictLocatedFileName(cPair.value);
						}else if(cPair.key.equals(Config.propertyLocatedPosition)){
							opt.setConflictLocatedPosition(Integer.parseInt(cPair.value));
						}else if(cPair.key.equals(Config.propertyCommentString)){
							opt.setCommentString(cPair.value);
						}
					}
					patch.conflictList.add(opt);
				} else if(conflictPropertyList[0].split(Config.equal)[1].equals(Config.propertyConflictTypeRename)){
					RenameOperation opt = new RenameOperation();
					for(int j = 1; i < conflictPropertyList.length;i++){
						StringKeyValuePair cPair;
						if(conflictPropertyList[i].split(Config.equal).length == 1){
							cPair = new StringKeyValuePair(conflictPropertyList[j].split(Config.equal)[0], null);
						}else{
							cPair = new StringKeyValuePair(conflictPropertyList[j].split(Config.equal)[0], conflictPropertyList[j].split(Config.equal)[1]);
						}
						if(cPair.key.equals(Config.propertyLocatedFile)){
							opt.setConflictLocatedFileName(cPair.value);
						}else if(cPair.key.equals(Config.propertyLocatedPosition)){
							opt.setConflictLocatedPosition(Integer.parseInt(cPair.value));
						}else if(cPair.key.equals(Config.propertyOriginIdentifier)){
							opt.setOriginIdentifier(cPair.value);
						}else if(cPair.key.equals(Config.propertyModifiedIdentifier)){
							opt.setOriginIdentifier(cPair.value);
						}
					}
					patch.conflictList.add(opt);
				}else if(conflictPropertyList[0].split(Config.equal)[1].equals(Config.propertyCastTotype)){
					AddCastingOperation opt = new AddCastingOperation();
					for(int j = 1; i < conflictPropertyList.length;i++){
						StringKeyValuePair cPair;
						if(conflictPropertyList[i].split(Config.equal).length == 1){
							cPair = new StringKeyValuePair(conflictPropertyList[j].split(Config.equal)[0], null);
						}else{
							cPair = new StringKeyValuePair(conflictPropertyList[j].split(Config.equal)[0], conflictPropertyList[j].split(Config.equal)[1]);
						}
						if(cPair.key.equals(Config.propertyLocatedFile)){
							opt.setConflictLocatedFileName(cPair.value);
						}else if(cPair.key.equals(Config.propertyLocatedPosition)){
							opt.setConflictLocatedPosition(Integer.parseInt(cPair.value));
						}else if(cPair.key.equals(Config.propertyOriginIdentifier)){
							opt.setOriginIdentifier(cPair.value);
						}else if(cPair.key.equals(Config.propertyModifiedIdentifier)){
							opt.setOriginIdentifier(cPair.value);
						}else if(cPair.key.equals(Config.propertyCastTotype)){
							opt.setCastToType(cPair.value);
						}
					}
					patch.conflictList.add(opt);
				}else if(conflictPropertyList[0].split(Config.equal)[1].equals(Config.propertyConflictTypeRemoveKeyword)){
					RemoveKeyWordOperation opt = new RemoveKeyWordOperation("");
					for(int j = 1; i < conflictPropertyList.length;i++){
						StringKeyValuePair cPair;
						if(conflictPropertyList[i].split(Config.equal).length == 1){
							cPair = new StringKeyValuePair(conflictPropertyList[j].split(Config.equal)[0], null);
						}else{
							cPair = new StringKeyValuePair(conflictPropertyList[j].split(Config.equal)[0], conflictPropertyList[j].split(Config.equal)[1]);
						}
						if(cPair.key.equals(Config.propertyLocatedFile)){
							opt.setConflictLocatedFileName(cPair.value);
						}else if(cPair.key.equals(Config.propertyLocatedPosition)){
							opt.setConflictLocatedPosition(Integer.parseInt(cPair.value));
						}else if(cPair.key.equals(Config.propertyKeyword)){
							opt.setKeyword(cPair.value);
						}else if(cPair.key.equals(Config.propertyFirstParameterStartingPosition)){
							opt.setFirstParameterStartingPosition(Integer.parseInt(cPair.value));
						}else if(cPair.key.equals(Config.propertyLastParameterEndingPosition)){
							opt.setLastParameterEndingPosition(Integer.parseInt(cPair.value));
						}
					}
					patch.conflictList.add(opt);
				}
			}
		return patch;
	}
}
